import * as fs from 'node:fs'
import * as path from 'node:path'
import { exec } from 'node:child_process'
import { commonInfo } from './common'

export function replaceNames(folderPath: string): void {
    const testJsonPath = path.join(folderPath, 'Test.json')
    let testJsonStr = fs.readFileSync(testJsonPath, { encoding: 'utf8', flag: 'r' })
    const names = getTestNames(testJsonStr)
    if (typeof names.bundle !== "string" || typeof names.module !== "string" || typeof names.hap !== "string") {
        console.error('\x1b[31m%s\x1b[0m', `Error reading Test.json ${JSON.stringify(names)}`)
        throw new Error('ERROR Bad Test.json names: ' + JSON.stringify(names))
    }
    commonInfo.bundleName = names.bundle
    testJsonStr = setModuleName(names.module, testJsonStr)
    testJsonStr = addSecondHap(names.hap, testJsonStr)
    fs.writeFileSync(testJsonPath, testJsonStr, 'utf8')
    setBuildGnName(names.hap, folderPath)
    setBundleName(names.bundle, folderPath)
}

function getTestNames(testJsonStr: string) {
    const testObj = JSON.parse(testJsonStr)
    let hapNames: any;
    for (const kit of testObj?.kits) {
        if (kit['test-file-name'] !== undefined) {
            hapNames = kit['test-file-name']
            break
        }
    }
    if ((hapNames?.length ?? 0) !== 1) {
        console.warn('\x1b[33m%s\x1b[0m', `The number of hap names is not equal to 1 (actually ${hapNames?.length}). Hap names: [${JSON.stringify(hapNames)}]`)
    }
    return {
        bundle: testObj?.driver?.['bundle-name'],
        module: testObj?.driver?.['module-name'],
        hap: hapNames?.[0]?.slice?.(0, -4),
    }
}

function setModuleName(moduleName: string, testJsonStr: string) {
    return moduleName !== 'entry_test'
        ? testJsonStr.replace(
            RegExp(`"module-name"\\s*:\\s*"${moduleName}"`, 'g'),
            '"module-name": "entry_test"'
        )
        : testJsonStr
}

function addSecondHap(hapName: string, testJsonStr: string) {
    let result = testJsonStr
    try {
        const fieldName = 'test-file-name'
        const startFieldNameIndex = testJsonStr.indexOf(fieldName)
        if (startFieldNameIndex < 0) throw new Error('addSecondHap startFieldNameIndex=' + startFieldNameIndex)
        const startFieldValueIndex = testJsonStr.indexOf('[', startFieldNameIndex + fieldName.length)
        if (startFieldValueIndex < 0) throw new Error('addSecondHap startFieldValueIndex=' + startFieldValueIndex)
        const endFieldValueIndex = testJsonStr.indexOf(']', startFieldValueIndex + 1)
        if (endFieldValueIndex < 0) throw new Error('addSecondHap endFieldValueIndex=' + endFieldValueIndex)
        const lb = getLineBreaker(testJsonStr)
        const tab = (n: number) => '    '.repeat(n)
        result = testJsonStr.substring(0, startFieldValueIndex + 1)
            + `${lb}${tab(4)}"${hapName}.hap",${lb}${tab(4)}"${hapName}Main.hap"${lb}${tab(3)}`
            + testJsonStr.substring(endFieldValueIndex)
    } catch (err) {
        console.warn('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
        console.warn('\x1b[33m%s\x1b[0m', `WARNING Hap name is not added. Please add ${hapName + 'Main.hap'} manually to Test.json.`)
        console.warn('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
    }
    return result
}

function setBuildGnName(testName: string, folderPath: string) {
    exec(`sed -i 's/YourHapName/${testName}/g' ${path.join(folderPath, 'BUILD.gn')}`, err => {
        if (err) {
            console.warn('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
            console.warn('\x1b[33m%s\x1b[0m', `WARNING ${testName} is not added to BUILD.gn. Please add ${testName} manually to BUILD.gn.`)
            console.warn('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
            return;
        }
    })
}

function setBundleName(bundleName: string, folderPath: string) {
    [
        path.join(folderPath, 'oh-package.json5').normalize(),
        path.join(folderPath, 'entry', 'src', 'main', 'module.json5').normalize(),
        path.join(folderPath, 'entry', 'src', 'ohosTest', 'ets', 'testrunner', 'OpenHarmonyTestRunner.ts').normalize(),
    ].forEach(p => exec(`sed -i 's/your_bundle_name/${bundleName}/g' ${p}`, err => {
        if (err) {
            console.warn('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
            console.warn('\x1b[33m%s\x1b[0m', `WARNING ${bundleName} is not added to ${p}. Please add ${bundleName} manually to ${p}.`)
            console.warn('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
            return;
        }
    }))
}

function getLineBreaker(text: string) {
    return text.includes('\r\n') ? '\r\n' : '\n'
}